package controller

import (
	"encoding/json"
	"example/application/blockchain"
	"example/application/lib"

	"example/application/util"
	"fmt"
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
)

/*
	- 创建新的交易
	@HttpParam: {id:string, Value:int, supplier:string, create_date:time.Time, company:string}
*/
func NewTransaction(context *gin.Context) {
	transaction := new(lib.Transaction)
	// err := context.ShouldBindJSON(transaction)
	err := context.ShouldBindJSON(transaction)
	if err != nil {
		context.String(http.StatusBadRequest, err.Error())
	}

	if transaction.Value == 0 || transaction.Supplier == "" || transaction.CreateDate.IsZero() || transaction.Company == "" {
		context.String(http.StatusBadRequest, "入参不能为空")
	}

	transaction.Id = util.Krand(10, 8)
	fmt.Println(transaction.Id + transaction.CreateDate.String())
	marshal, err := json.Marshal(transaction)
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}
	fmt.Println(string(marshal))
	resp, err := blockchain.ChannelExecute("newTransaction", [][]byte{
		marshal,
	})
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}
	context.JSON(http.StatusOK, resp.Payload)
}

/*
	@Param: {id:string, supplier:string}
*/
func ConfirmTransaction(context *gin.Context) {
	transaction := new(lib.Transaction)
	if err := context.ShouldBindJSON(transaction); err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	if transaction.Id == "" || transaction.Supplier == "" {
		context.String(http.StatusBadRequest, "入参不能为空")
	}

	marshal, err := json.Marshal(transaction)
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	resp, err := blockchain.ChannelExecute("confirmTransaction", [][]byte{
		marshal,
	})
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}
	context.JSON(http.StatusOK, resp.Payload)
}

/*
	@Param: {id:string, company:string, financial_org:string, repayment_date:time.Time}
*/
func ApplyPayForAnother(context *gin.Context) {
	transaction := new(lib.Transaction)
	if err := context.ShouldBindJSON(transaction); err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	if transaction.Id == "" || transaction.Company == "" || transaction.FinancialOrg == "" || transaction.RepaymentDate.IsZero() {
		context.String(http.StatusBadRequest, "入参不能为空")
	}

	marshal, err := json.Marshal(transaction)
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	resp, err := blockchain.ChannelExecute("applyPayForAnother", [][]byte{
		marshal,
	})
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}
	context.JSON(http.StatusOK, resp.Payload)
}

/*
	@Paramm: {id:string,PaymentTxNumber:string,financial_org:string,payment_date:time.Time}
*/
func PayTransaction(context *gin.Context) {
	transaction := new(lib.Transaction)
	if err := context.ShouldBindJSON(transaction); err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	if transaction.Id == "" || transaction.PaymentTxNumber == "" || transaction.FinancialOrg == "" || transaction.PaymentDate.IsZero() {
		context.String(http.StatusBadRequest, "入参不能为空")
	}

	marshal, err := json.Marshal(transaction)
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	resp, err := blockchain.ChannelExecute("payTransaction", [][]byte{
		marshal,
	})
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}
	context.JSON(http.StatusOK, resp.Payload)
}

/*
	@Param: {id:string, supplier:string}
*/
func AffirmPay(context *gin.Context) {
	transaction := new(lib.Transaction)
	if err := context.ShouldBindJSON(transaction); err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	if transaction.Id == "" || transaction.Supplier == "" {
		context.String(http.StatusBadRequest, "入参不能为空")
	}

	marshal, err := json.Marshal(transaction)
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	resp, err := blockchain.ChannelExecute("affirmPay", [][]byte{
		marshal,
	})
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}
	context.JSON(http.StatusOK, resp.Payload)
}

/*
	@Param: {id:string,description:string,financial_org:string}
*/
func RefusePayTransaction(context *gin.Context) {
	transaction := new(lib.Transaction)
	if err := context.ShouldBindJSON(transaction); err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	if transaction.Id == "" || transaction.Description == "" || transaction.FinancialOrg == "" {
		context.String(http.StatusBadRequest, "入参不能为空")
	}

	marshal, err := json.Marshal(transaction)
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	resp, err := blockchain.ChannelExecute("refusePayTransaction", [][]byte{
		marshal,
	})
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}
	context.JSON(http.StatusOK, resp.Payload)
}

/*
	@Param: {id:string,shipment_number:string,supplier:string}
*/
func UpdateShipmentInfo(context *gin.Context) {
	transaction := new(lib.Transaction)
	if err := context.ShouldBindJSON(transaction); err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	if transaction.Id == "" || transaction.ShipmentNumber == "" || transaction.Supplier == "" {
		context.String(http.StatusBadRequest, "入参不能为空")
	}

	marshal, err := json.Marshal(transaction)
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	resp, err := blockchain.ChannelExecute("updateShipmentInfo", [][]byte{
		marshal,
	})
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}
	context.JSON(http.StatusOK, resp.Payload)
}

/*
	@Param: {id:string,company:string}
*/
func VerifyShipmentInfo(context *gin.Context) {
	transaction := new(lib.Transaction)
	if err := context.ShouldBindJSON(transaction); err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	if transaction.Id == "" || transaction.Company == "" {
		context.String(http.StatusBadRequest, "入参不能为空")
	}

	marshal, err := json.Marshal(transaction)
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	resp, err := blockchain.ChannelExecute("verifyShipmentInfo", [][]byte{
		marshal,
	})
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}
	context.JSON(http.StatusOK, resp.Payload)
}

/*
	@Param:{id:string,repayment_tx_number:string,tx_to_update:time.Time,company:string}
*/
func RepayTransaction(context *gin.Context) {
	transaction := new(lib.Transaction)
	if err := context.ShouldBindJSON(transaction); err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	if transaction.Id == "" || transaction.RepaymentTxNumber == "" || transaction.RepayDate.IsZero() || transaction.Company == "" {
		context.String(http.StatusBadRequest, "入参不能为空")
	}

	marshal, err := json.Marshal(transaction)
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	resp, err := blockchain.ChannelExecute("repayTransaction", [][]byte{
		marshal,
	})
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}
	context.JSON(http.StatusOK, resp.Payload)
}

/*
	@Param:  {id:string,financial_org:string}
*/
func VerifyRepay(context *gin.Context) {
	transaction := new(lib.Transaction)
	if err := context.ShouldBindJSON(transaction); err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	if transaction.Id == "" || transaction.FinancialOrg == "" {
		context.String(http.StatusBadRequest, "入参不能为空")
	}

	marshal, err := json.Marshal(transaction)
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	resp, err := blockchain.ChannelExecute("verifyRepay", [][]byte{
		marshal,
	})
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}
	context.JSON(http.StatusOK, resp.Payload)
}

/*
	@Param: nowTime:time.Time
*/
func AutoRepay(context *gin.Context) {
	nowTime, is_null := context.GetPostForm("now_time")
	if !is_null {
		context.String(http.StatusBadRequest, "入参不能为空")
	}

	resp, err := blockchain.ChannelExecute("autoRepay", [][]byte{
		[]byte(nowTime),
	})
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	context.JSON(http.StatusOK, resp.Payload)
}

/*
	@Param:  buyer:string 买方公司名
*/
func GetTrByBuyer(context *gin.Context) {
	key := context.Query("buyer")
	if key == "" {
		context.String(http.StatusBadRequest, "入参不能为空")
	}

	resp, err := blockchain.ChannelQuery("getTrByBuyer", [][]byte{
		[]byte(key),
	})
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	context.JSON(http.StatusOK, string(resp.Payload))
}

func GetTransactions(context *gin.Context) {
	key := context.Query("keys")
	fmt.Println("keys:" + key)
	keyByte := []byte("[]")
	var err error
	if key != "" {
		keyArr := strings.Split(key, ",")
		keyByte, err = json.Marshal(keyArr)
		if err != nil {
			context.String(http.StatusInternalServerError, err.Error()+"错误")
		}
	}

	resp, err := blockchain.ChannelQuery("getTransactions", [][]byte{
		keyByte,
	})
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	context.JSON(http.StatusOK, string(resp.Payload))
}

func GetTransactionHistory(context *gin.Context) {
	key := context.Query("key")
	if key == "" {
		context.String(http.StatusBadRequest, "入参不能为空")
	}

	resp, err := blockchain.ChannelQuery("getTransactionHistory", [][]byte{
		[]byte(key),
	})
	if err != nil {
		context.String(http.StatusInternalServerError, err.Error())
	}

	context.JSON(http.StatusOK, string(resp.Payload))
}
